﻿using Google.Protobuf;
using Grpc.Core;
using Grpc.Net.Client;
using GrpcServer.Web.protos;

namespace GrpcClient
{
    public class Program
    {
        public async static Task Main(string[] args)
        {
            using var channel = GrpcChannel.ForAddress("https://localhost:7277");
            var client = new EmployeeService.EmployeeServiceClient(channel);

            var option = 5;
            switch (option)
            {
                case 1:
                    await GetByNoAsync(client);
                    break;
                case 2:
                    await GetAllAsync(client);
                    break;
                case 3:
                    await AddPhotoAsync(client);
                    break;
                case 5:
                    await SaveAllAsync(client);
                    break;
            }

            Console.WriteLine($"Press any key to exit.");
            Console.ReadKey();
        }

        private static async Task GetByNoAsync(EmployeeService.EmployeeServiceClient client)
        {
            var md = new Metadata
            {
                {"username","mankiw"},
                { "role","administrator"}
            };
            var response = await client.GetByNoAsync(new GetByNoRequest
            {
                No = 1904
            }, md);
            Console.WriteLine($"Response messasge:{response}");
        }

        private static async Task GetAllAsync(EmployeeService.EmployeeServiceClient client)
        {
            //实际上不需要参数，但是在grpc中不需要对象也需要传一个空的
            //call对象需要在使用后被释放
            using var call = client.GetAll(new GetAllRequest());
            var responseStream = call.ResponseStream;
            //使用responseStream的moveNext方法
            while (await responseStream.MoveNext())
            {
                Console.WriteLine(responseStream.Current.Employee);
            }
        }

        private static async Task AddPhotoAsync(EmployeeService.EmployeeServiceClient client)
        {
            var md = new Metadata
            {
                {"username","mankiw"},
                { "role","administrator"}
            };
            //需要一个filestream
            FileStream fs = File.OpenRead("D:\\A.Regarding my desire to become a good person\\CODE\\grpc_code\\GrpcClient\\xinxin.jpg");
            //调用addphoto,可以不传参数
            using var call = client.AddPhoto(md);
            //
            var stream = call.RequestStream;
            while (true)
            {
                byte[] buffer = new byte[100000];
                //将fs中内容读取到buffer中，从0读到length
                int numRead = await fs.ReadAsync(buffer, 0, buffer.Length);
                if (numRead == 0)
                {
                    break;
                }
                if (numRead < buffer.Length)
                {
                    //将buffer数组长度改为numRead大小
                    Array.Resize(ref buffer, numRead);
                }
                await stream.WriteAsync(new AppPhotoRequest()
                {
                    Data = ByteString.CopyFrom(buffer)
                });
            }
            await stream.CompleteAsync();
            var res = await call.ResponseAsync;
            Console.WriteLine(res.IsOk);
        }

        private static async Task SaveAllAsync(EmployeeService.EmployeeServiceClient client)
        {
            var employees = new List<Employee>()
            {
                new Employee()
                {
                    No = 1111,
                    FirstName = $"firstName{1111}",
                    MonthSalary = new MonthSalary
                    {
                        Basic = 10,
                    }
                },
                new Employee()
                {
                    No = 2222,
                    FirstName = $"firstName{2222}",
                }
            };
            using var call = client.SaveAll();

            var requestStream = call.RequestStream;
            var responseStream = call.ResponseStream;

            var responseTask = Task.Run(async () =>
            {
                while (await responseStream.MoveNext())
                {
                    Console.WriteLine($"Saved:{responseStream.Current.Employee}");
                }
            });

            foreach (var emp in employees)
            {
                await requestStream.WriteAsync(new EmployeeRequest()
                {
                    Employee = emp
                });
            }

            await requestStream.CompleteAsync();
            await responseTask;
        }
    }
}